from sqlalchemy import Column, String, inspect, text, UUID, func
from service.database import Base, SessionLocal


class Post(Base):
    def __init__(self, data: dict = None, **kw):
        super().__init__(**kw)
        if data:
            self.from_dict(data)

    __tablename__ = "post"
    id = Column(UUID(), primary_key=True, server_default=text("uuid_generate_v4()"))
    time = Column(String)
    title = Column(String)
    content = Column(String)
    username = Column(String)

    def todict(self):
        result = {}
        for c in inspect(self).mapper.column_attrs:
            value = getattr(self, c.key)
            if value is not None:
                result[c.key] = str(value)
        return result

    def from_dict(self, data: dict):
        for field in ['title', 'content', 'username', 'time']:
            if field in data and data[field] is not None:
                setattr(self, field, data[field])


def create_post(post: dict) -> bool:
    db = SessionLocal()
    try:
        post = Post(data=post)
        db.add(post)
        db.commit()
        return True
    finally:
        db.close()


def delete_post(id: str) -> bool:
    db = SessionLocal()
    try:
        post = db.query(Post).filter(Post.id == id).first()
        if post:
            db.delete(post)
            db.commit()
            return True
        else:
            return False
    finally:
        db.close()


def get_posts(n: int = 1):
    db = SessionLocal()
    try:
        post = db.query(Post).order_by(Post.time.desc()).limit(n).all()
        return post
    finally:
        db.close()


def get_total(username: str = None) -> int:
    db = SessionLocal()
    try:
        if username:
            total = db.query(func.count(Post.id)).filter(Post.username == username).scalar()
        else:
            total = db.query(func.count(Post.id)).scalar()
        return total
    finally:
        db.close()


def get_post(id: str):
    db = SessionLocal()
    try:
        post = db.query(Post).filter(Post.id == id).first()
        return post
    finally:
        db.close()


def page(page_number: int, page_size: int, username: str = None):
    db = SessionLocal()
    try:
        if username:
            post = db.query(Post).filter(Post.username == username).order_by(Post.time.desc()).limit(page_size).offset(
                (page_number - 1) * page_size).all()
        else:
            post = (db.query(Post).order_by(Post.time.desc()).limit(page_size).
                    offset((page_number - 1) * page_size).all())
        return post
    finally:
        db.close()


def update_post(post: dict) -> bool:
    db = SessionLocal()
    try:
        query_post = db.query(Post).filter(Post.id == post['id']).first()
        if query_post:
            query_post.from_dict(post)
            db.commit()
            return True
        else:
            return False
    finally:
        db.close()


def replace_username(username: str, new_username: str):
    db = SessionLocal()
    try:
        posts = db.query(Post).filter(Post.username == username).all()
        for post in posts:
            post.username = new_username
        db.commit()
        return True
    finally:
        db.close()
